import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  CancelTokenSource,
  InternalAxiosRequestConfig,
} from 'axios';
import useUserStore from '@/store/user';

interface RequestParams {
  [key: string]: boolean | string | number | undefined | File | Blob | FormData; // 如果参数结构不确定，可以使用索引签名
}

interface ResponseData {
  code: number;
  message: string;
  data: unknown;
  [key: string]: unknown; // 允许其他未知属性
}

class Request {
  // 定义 Axios 实例
  private instance: AxiosInstance;
  // 定义取消令牌源
  private cancelTokenSource: CancelTokenSource | null = null;

  // 构造函数，传入 Axios 请求配置
  constructor(config: AxiosRequestConfig) {
    // 创建 Axios 实例
    this.instance = axios.create(config);

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        const { token } = useUserStore.getState(); // 动态获取 token
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
          console.log(config.headers, '请求头');
        }
        console.log(config, '请求拦截器');
        return config;
      },
      (error) => {
        return Promise.reject(error);
      },
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        console.log(response, '响应拦截器');
        if (response.status !== 200 && response.data.code !== 200) {
          return Promise.reject(false);
        }

        return response.data;
      },
      (error) => {
        return Promise.reject(error);
      },
    );
  }

  // 取消当前请求
  public cancelRequest(message?: string): void {
    if (this.cancelTokenSource) {
      this.cancelTokenSource.cancel(message || '请求已取消');
      this.cancelTokenSource = null;
    }
  }

  // 通用请求方法
  public async request<T extends ResponseData>(
    config: AxiosRequestConfig,
  ): Promise<AxiosResponse<T>> {
    this.cancelTokenSource = axios.CancelToken.source();
    config.cancelToken = this.cancelTokenSource.token;
    try {
      const result = await this.instance.request<T>(config);
      console.log(result, '请求结果');
      if (result?.code !== 200) {
        return Promise.reject(false);
      } else {
        return Promise.resolve(result);
      }
    } catch (error) {
      console.error('请求出错:', error);
      throw error;
    }
  }

  // 封装 get 方法
  public async get<T = unknown>(
    url: string,
    params?: RequestParams,
  ): Promise<AxiosResponse<T>> {
    return this.request<T>({ url, method: 'get', params });
  }

  public async post<T = unknown>(
    url: string,
    data?: RequestParams | FormData,
  ): Promise<AxiosResponse<T>> {
    // 如果 data 是 FormData，则移除 Content-Type 头，让浏览器自动设置
    if (data instanceof FormData) {
      return this.request<T>({
        url,
        method: 'post',
        data,
        headers: {
          ...this.instance.defaults.headers,
          'Content-Type': undefined, // 让浏览器自动设置
        },
      });
    }
    return this.request<T>({ url, method: 'post', data });
  }

  public async delete<T = unknown>(
    url: string,
    params?: RequestParams,
  ): Promise<AxiosResponse<T>> {
    return this.request<T>({ url, method: 'delete', params });
  }

  public async put<T = unknown>(
    url: string,
    data?: RequestParams,
  ): Promise<AxiosResponse<T>> {
    return this.request<T>({ url, method: 'put', data });
  }
}

// 创建实例并导出
const request = new Request({
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
});

export default request;
